use std::path::PathBuf;
use std::sync::OnceLock;

/// 返回用户主目录的路径。
pub fn home_dir() -> &'static PathBuf {
    static HOME_DIR: OnceLock<PathBuf> = OnceLock::new();
    HOME_DIR.get_or_init(|| dirs::home_dir().expect("failed to determine home directory"))
}


/// 返回使用的配置目录的路径
///
/// # Arguments
///
/// * `name` - 配置目录的名称
///
/// # Returns
///
pub fn config_dir(name: &str) -> &'static PathBuf {
    static CONFIG_DIR: OnceLock<PathBuf> = OnceLock::new();
    CONFIG_DIR.get_or_init(|| {
        if cfg!(target_os = "windows") {
            return dirs::config_dir()
                .expect("failed to determine RoamingAppData directory")
                .join(name);
        }

        if cfg!(any(target_os = "linux", target_os = "freebsd")) {
            return if let Ok(flatpak_xdg_config) = std::env::var("FLATPAK_XDG_CONFIG_HOME") {
                flatpak_xdg_config.into()
            } else {
                dirs::config_dir().expect("failed to determine XDG_CONFIG_HOME directory")
            }
                .join(name);
        }

        home_dir().join(".config").join(name)
    })
}

/// 返回支持目录的路径。
/// # Arguments
///
/// * `name` - 配置目录的名称
///
/// # Returns
///
pub fn support_dir(name: &str) -> &'static PathBuf {
    static SUPPORT_DIR: OnceLock<PathBuf> = OnceLock::new();
    SUPPORT_DIR.get_or_init(|| {
        if cfg!(target_os = "macos") {
            return home_dir().join("Library/Application Support").join(name);
        }

        if cfg!(any(target_os = "linux", target_os = "freebsd")) {
            return if let Ok(flatpak_xdg_data) = std::env::var("FLATPAK_XDG_DATA_HOME") {
                flatpak_xdg_data.into()
            } else {
                dirs::data_local_dir().expect("failed to determine XDG_DATA_HOME directory")
            }
                .join(name);
        }

        if cfg!(target_os = "windows") {
            return dirs::data_local_dir()
                .expect("failed to determine LocalAppData directory")
                .join(name);
        }

        config_dir(name).clone()
    })
}

/// 返回临时目录的路径。
/// # Arguments
///
/// * `name` - 配置目录的名称
///
/// # Returns
///
pub fn temp_dir(name: &str) -> &'static PathBuf {
    static TEMP_DIR: OnceLock<PathBuf> = OnceLock::new();
    TEMP_DIR.get_or_init(|| {
        if cfg!(target_os = "macos") {
            return dirs::cache_dir()
                .expect("failed to determine cachesDirectory directory")
                .join(name);
        }

        if cfg!(target_os = "windows") {
            return dirs::cache_dir()
                .expect("failed to determine LocalAppData directory")
                .join(name);
        }

        if cfg!(any(target_os = "linux", target_os = "freebsd")) {
            return if let Ok(flatpak_xdg_cache) = std::env::var("FLATPAK_XDG_CACHE_HOME") {
                flatpak_xdg_cache.into()
            } else {
                dirs::cache_dir().expect("failed to determine XDG_CACHE_HOME directory")
            }
                .join(name);
        }

        home_dir().join(".cache").join(name)
    })
}

/// 返回 logs 目录的路径。
pub fn logs_dir(name: &str) -> &'static PathBuf {
    static LOGS_DIR: OnceLock<PathBuf> = OnceLock::new();
    LOGS_DIR.get_or_init(|| {
        if cfg!(target_os = "macos") {
            home_dir().join("Library/Logs").join(name)
        } else {
            support_dir(name).join("logs")
        }
    })
}

mod tests {
    use std::path::Path;
    use std::env;

    use super::*;

    // 辅助函数：设置和清理环境变量
    fn setup_and_cleanup_env<F>(test_func: F)
    where
        F: FnOnce() -> (),
    {
        env::set_var("HOME", "/mock");
        test_func();
        env::remove_var("HOME");
    }

    #[cfg(target_os = "macos")]
    #[test]
    fn test_config_dir() {
        setup_and_cleanup_env(|| {
            let config_path = config_dir("myapp");
            assert_eq!(config_path.as_path(), Path::new("/mock/.config/myapp"));
        });
    }

    #[cfg(target_os = "macos")]
    #[test]
    fn test_logs_dir() {
        setup_and_cleanup_env(|| {
            let logs_path = logs_dir("myapp");
            assert_eq!(logs_path.as_path(), Path::new("/mock/Library/Logs/myapp"));
        });
    }

    #[cfg(target_os = "macos")]
    #[test]
    fn test_temp_dir() {
        setup_and_cleanup_env(|| {
            let temp_path = temp_dir("myapp");
            assert_eq!(temp_path.as_path(), Path::new("/mock/Library/Caches/myapp"));
        });
    }

    #[cfg(target_os = "macos")]
    #[test]
    fn test_support_dir() {
        setup_and_cleanup_env(|| {
            let support_path = support_dir("myapp");
            assert_eq!(support_path.as_path(), Path::new("/mock/Library/Application Support/myapp"));
        });
    }
}



